﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using haptic.src.engine.animation;

namespace haptic.src.engine.render
{
    public class Renderer : GameComponent
    {
        #region Constructors
        public Renderer(Microsoft.Xna.Framework.Game oGame)
            : base(oGame)
        {
            Game.Components.Add(this);
            UpdateProjectionMatrix();
            m_oContent = new ContentManager(Game.Services);
        }
        #endregion

        #region Load
        public void Load()
        {
            m_oSpriteEffect = m_oContent.Load<Effect>(@"Content/Shaders/SpriteBatch");
        }
        protected void Unload()
        {
            m_oContent.Unload();
        }
        #endregion

        #region Edit
        public void Resize(float fWidth, float fHeight)
        {
            m_fWidth = fWidth;
            m_fHeight = fHeight;
            m_fAspectRatio = fWidth / fHeight;
            UpdateProjectionMatrix();
        }
        #endregion

        #region Update
        private void UpdateProjectionMatrix()
        {
            m_mProjection = Matrix.CreateOrthographic(m_fWidth, m_fHeight, F_NEAR_CLIP_PLANE, F_FAR_CLIP_PLANE);
        }
        public override void Update(GameTime oGameTime)
        {
            if (m_oCameraManager != null && m_oCameraManager.GetCurrent() != null)
            {
                m_vCameraOffset = -m_oCameraManager.GetCurrent().m_vPosition;
            }
           
            base.Update(oGameTime);
        }
        #endregion

        #region Draw
        public void SetDepth(float fDepth)
        {
            Matrix mMat = Matrix.Identity;
            if (m_oCameraManager != null && m_oCameraManager.GetCurrent() != null)
            {
                //m_oSpriteEffect.Parameters["fDepth"].SetValue(fDepth);
            }
        }
        public void BeginRender(float fDepth)
        {
            Matrix mMat = Matrix.Identity;
            if (m_oCameraManager != null && m_oCameraManager.GetCurrent() != null)
            {
                mMat = m_oCameraManager.GetCurrent().GetWorldMat(m_fWidth, m_fHeight, fDepth);
            }
            if (m_oSpriteBatch != null)
                m_oSpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None, mMat);

            if (m_oSpriteEffect != null)
            {
                Vector2 viewportSize = new Vector2(m_fWidth, m_fHeight);
                m_oSpriteEffect.Parameters["ViewportSize"].SetValue(viewportSize);

                m_oSpriteEffect.Begin();
                m_oSpriteEffect.CurrentTechnique.Passes[0].Begin();
            }
        }
        public void EndRender()
        {
            if (m_oSpriteEffect != null)
            {
                m_oSpriteEffect.CurrentTechnique.Passes[0].End();
                m_oSpriteEffect.End();
            }
            if (m_oSpriteBatch != null)
                m_oSpriteBatch.End();
        }
        public void DrawSprite(Texture2D oTexture, Vector2 vOrigin, Rectangle oRect)
        {
            Debug.Assert(m_oSpriteBatch != null);
            m_oSpriteBatch.Draw(oTexture, vOrigin, oRect, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
        }

        public void DrawSprite(Sprite oSprite, Vector2 vOrigin, Rectangle oRect)
        {
            Debug.Assert(m_oSpriteBatch != null);
            m_oSpriteBatch.Draw(oSprite.oTexture, vOrigin, oRect, Color.White, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.0f);
        }

        public void DrawSprite(Sprite oSprite, Vector2 vOrigin, Rectangle oRect, SpriteEffects eSpriteEffects)
        {
            Debug.Assert(m_oSpriteBatch != null);
            m_oSpriteBatch.Draw(oSprite.oTexture, vOrigin, oRect, Color.White, 0.0f, Vector2.Zero, 1.0f, eSpriteEffects, 0.0f);
        }
        #endregion

        #region Constants
        private float F_NEAR_CLIP_PLANE = 0.1f;
        private float F_FAR_CLIP_PLANE = 30000.0f;
        //private float F_FOV = 40.0f;
        #endregion

        #region Attributes
        public SpriteBatch m_oSpriteBatch;
        private Effect m_oSpriteEffect;
        private Matrix m_mProjection = Matrix.Identity;
        public Matrix projectionMatrix { get { return m_mProjection; } }
        private float m_fWidth = 1.0f;
        public float width { get { return m_fWidth; } }
        private float m_fHeight = 1.0f;
        public float height { get { return m_fHeight; } }
        private float m_fAspectRatio = 1.0f;
        private Vector2 m_vCameraOffset = Vector2.Zero;
        public Vector2 vCameraOffset { get { return m_vCameraOffset; } }
        private ContentManager m_oContent;
        public CameraManager m_oCameraManager;
        #endregion
    }
}
